package com.example.androidone.usb;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;

import com.example.androidone.player.VideoDecoder;
import com.example.androidone.utils.NALParser;
import com.example.androidone.utils.Constants;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

public class MockUsbDataReceiver {
    private static final String TAG = "MockUsbReceiver";
    private static final int MSG_PROCESS_DATA = 1;
    private static final int RETRY_DELAY_MS = 100;
    private static final int NAL_PROCESSING_DELAY_MS = 5;

    private final Context context;
    private final VideoDecoder decoder;
    private final NALParser nalParser;

    private HandlerThread workThread;
    private Handler workHandler;
    private final Handler mainHandler;
    private InputStream inputStream;
    private final AtomicBoolean isRunning = new AtomicBoolean(false);

    public MockUsbDataReceiver(Context context, VideoDecoder decoder) {
        this.context = context;
        this.decoder = decoder;
        this.nalParser = new NALParser();
        this.mainHandler = new Handler(Looper.getMainLooper());
    }

    public void start() {
        if (isRunning.get()) {
            Log.w(TAG, "Already running");
            return;
        }

        try {
            initializeWorkThread();
            openInputStream();
            startTransmission();
        } catch (Exception e) {
            Log.e(TAG, "Failed to start transmission", e);
            cleanup();
        }
    }

    private void initializeWorkThread() {
        workThread = new HandlerThread("USB_Data_Processor");
        workThread.start();
        workHandler = new Handler(workThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == MSG_PROCESS_DATA) {
                    processNextChunk();
                }
            }
        };
    }

    private void openInputStream() throws IOException {
        inputStream = context.getAssets().open("test.h265");
        inputStream.mark(Integer.MAX_VALUE);
    }

    private void startTransmission() {
        isRunning.set(true);
        workHandler.sendEmptyMessage(MSG_PROCESS_DATA);
        Log.d(TAG, "Started mock transmission");
    }

    private void processNextChunk() {
        if (!isRunning.get()) return;

        try {
            byte[] buffer = new byte[Constants.BUFFER_SIZE];
            int bytesRead = inputStream.read(buffer);

            if (bytesRead > 0) {
                byte[] data = Arrays.copyOf(buffer, bytesRead);
                List<byte[]> nalUnits = nalParser.parseNALUnits(data);

                for (byte[] nalUnit : nalUnits) {
                    if (!isRunning.get()) return;
                    decoder.decode(nalUnit);
                    // 延迟调整到更合理的值
                    SystemClock.sleep(16); // ~60fps
                }

                // 使用固定的帧间隔
                scheduleNextProcessing(33); // ~30fps
            } else {
                handleEndOfStream();
            }
        } catch (Exception e) {
            handleProcessingError(e);
        }
    }

    private void processNALUnits(byte[] data) throws InterruptedException {
        List<byte[]> nalUnits = nalParser.parseNALUnits(data);
        for (byte[] nalUnit : nalUnits) {
            if (!isRunning.get()) return;

            decoder.decode(nalUnit);
            SystemClock.sleep(NAL_PROCESSING_DELAY_MS);
        }
    }

    private void scheduleNextProcessing(long delay) {
        if (isRunning.get()) {
            workHandler.sendEmptyMessageDelayed(MSG_PROCESS_DATA, delay);
        }
    }

    private void handleEndOfStream() throws IOException {
        if (isRunning.get()) {
            inputStream.reset();
            scheduleNextProcessing(RETRY_DELAY_MS);
        }
    }

    private void handleProcessingError(Exception e) {
        Log.e(TAG, "Error processing data", e);
        mainHandler.post(() -> {
            if (isRunning.get()) {
                stop();
            }
        });
    }

    public void stop() {
        if (!isRunning.get()) {
            return;
        }

        cleanup();
        Log.d(TAG, "Stopped mock transmission");
    }

    private void cleanup() {
        isRunning.set(false);

        if (workHandler != null) {
            workHandler.removeCallbacksAndMessages(null);
        }

        if (workThread != null) {
            workThread.quitSafely();
            workThread = null;
        }

        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                Log.e(TAG, "Error closing stream", e);
            }
            inputStream = null;
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            stop();
        } finally {
            super.finalize();
        }
    }
}